<!DOCTYPE html>
<html lang="zh">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>蛋哥的图灵机加法模拟器</title>
    <style>
        :root {
            --primary: #3498db;
            --success: #2ecc71;
            --warning: #f39c12;
            --danger: #e74c3c;
            --dark: #2c3e50;
            --light: #ecf0f1;
            --gray: #95a5a6;
            --accent: #9b59b6;
        }
        
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
        }
        
        body {
            background: linear-gradient(135deg, #1a2a6c, #2c3e50);
            color: #ecf0f1;
            min-height: 100vh;
            padding: 20px;
            display: flex;
            justify-content: center;
            align-items: center;
        }
        
        .container {
            width: 100%;
            max-width: 1300px;
            background: rgba(25, 35, 60, 0.9);
            backdrop-filter: blur(5px);
            border-radius: 15px;
            box-shadow: 0 10px 30px rgba(0, 0, 0, 0.4);
            overflow: hidden;
            border: 1px solid rgba(255, 255, 255, 0.1);
        }
        
        header {
            background: rgba(15, 25, 50, 0.9);
            padding: 20px;
            text-align: center;
            border-bottom: 1px solid rgba(255, 255, 255, 0.1);
        }
        
        h1 {
            font-size: 2.2rem;
            margin-bottom: 10px;
            background: linear-gradient(90deg, var(--primary), var(--success));
            -webkit-background-clip: text;
            -webkit-text-fill-color: transparent;
        }
        
        .subtitle {
            font-size: 1rem;
            color: #bdc3c7;
            max-width: 800px;
            margin: 0 auto;
            line-height: 1.6;
        }
        
        .main-content {
            padding: 20px;
            display: flex;
            flex-wrap: wrap;
            gap: 20px;
        }
        
        .left-panel {
            flex: 3;
            min-width: 300px;
            display: flex;
            flex-direction: column;
            gap: 20px;
        }
        
        .right-panel {
            flex: 2;
            min-width: 250px;
        }
        
        .input-section {
            display: flex;
            flex-wrap: wrap;
            gap: 15px;
            justify-content: center;
            margin-bottom: 0px;
        }
        
        .input-group {
            display: flex;
            flex-direction: column;
            min-width: 150px;
        }
        
        .input-group label {
            margin-bottom: 8px;
            font-weight: 600;
            color: var(--light);
            display: flex;
            align-items: center;
            gap: 8px;
        }
        
        .input-wrapper {
            position: relative;
        }
        
        input {
            width: 100%;
            padding: 10px 15px;
            background: rgba(20, 30, 50, 0.7);
            border: 2px solid var(--primary);
            border-radius: 8px;
            color: white;
            font-size: 1rem;
            transition: all 0.3s;
        }
        
        input:focus {
            outline: none;
            border-color: var(--success);
            box-shadow: 0 0 0 3px rgba(46, 204, 113, 0.3);
        }
        
        .unary-explanation {
            background: rgba(44, 62, 80, 0.5);
            padding: 12px;
            border-radius: 8px;
            margin-top: 15px;
            font-size: 0.9rem;
            line-height: 1.6;
            text-align: center;
        }
        
        .controls {
            display: flex;
            justify-content: center;
            flex-wrap: wrap;
            gap: 10px;
            margin: 0px 0;
        }
        
        button {
            padding: 12px 20px;
            border: none;
            border-radius: 8px;
            font-weight: 600;
            font-size: 1rem;
            cursor: pointer;
            transition: all 0.3s;
            display: flex;
            align-items: center;
            justify-content: center;
            gap: 8px;
            box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
            min-width: 120px;
        }
        
        button:disabled {
            opacity: 0.7;
            cursor: not-allowed;
        }
        
        button:not(:disabled):hover {
            transform: translateY(-2px);
            box-shadow: 0 6px 12px rgba(0, 0, 0, 0.3);
        }
        
        #initBtn {
            background: linear-gradient(135deg, var(--primary), #2980b9);
            color: white;
        }
        
        #stepBtn {
            background: linear-gradient(135deg, var(--success), #27ae60);
            color: white;
        }
        
        #runBtn {
            background: linear-gradient(135deg, var(--warning), #d35400);
            color: white;
        }
        
        #resetBtn {
            background: linear-gradient(135deg, var(--danger), #c0392b);
            color: white;
        }
        
        .tape-container {
            position: relative;
            background: rgba(15, 25, 40, 0.8);
            border-radius: 12px;
            padding: 20px 10px;
            margin: 10px 0;
            overflow: hidden;
        }
        
        .tape-scroll {
            display: flex;
            overflow-x: auto;
            padding: 10px 0;
            scrollbar-width: none;
            justify-content: center;
        }
        
        .tape-scroll::-webkit-scrollbar {
            display: none;
        }
        
        .tape {
            display: flex;
            position: relative;
        }
        
        .cell {
            width: 60px;
            height: 80px;
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: center;
            background: rgba(25, 35, 60, 0.9);
            border: 2px solid var(--primary);
            border-radius: 8px;
            font-size: 1.5rem;
            font-weight: bold;
            margin: 0 4px;
            position: relative;
            transition: all 0.3s;
            box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
            color: white;
        }
        
        .cell.active {
            background: rgba(255, 234, 167, 0.25);
            border-color: #f1c40f;
            transform: scale(1.08);
            z-index: 10;
            box-shadow: 0 0 15px rgba(241, 196, 15, 0.5);
        }
        
        .cell.index {
            position: absolute;
            bottom: 8px;
            font-size: 0.7rem;
            color: var(--gray);
        }
        
        .head {
            position: absolute;
            top: -40px;
            font-size: 2rem;
            color: var(--danger);
            text-shadow: 0 0 10px rgba(231, 76, 60, 0.7);
            transition: left 0.5s cubic-bezier(0.34, 1.56, 0.64, 1);
            z-index: 20;
        }
        
        .head::after {
            content: '读写头';
            position: absolute;
            top: -30px;
            left: 50%;
            transform: translateX(-50%);
            font-size: 0.8rem;
            background: rgba(231, 76, 60, 0.9);
            padding: 2px 8px;
            border-radius: 15px;
            white-space: nowrap;
        }
        
        .info-panel {
            display: flex;
            flex-direction: column;
            gap: 15px;
            margin-top: 10px;
        }
        
        .state-display {
            background: rgba(44, 62, 80, 0.7);
            padding: 15px;
            border-radius: 8px;
            display: flex;
            align-items: center;
            gap: 12px;
        }
        
        .state-icon {
            width: 50px;
            height: 50px;
            border-radius: 50%;
            background: rgba(52, 152, 219, 0.2);
            display: flex;
            align-items: center;
            justify-content: center;
            font-size: 1.5rem;
            flex-shrink: 0;
            color: var(--primary);
        }
        
        .state-info {
            flex-grow: 1;
        }
        
        .state-info h3 {
            font-size: 0.95rem;
            color: var(--gray);
            margin-bottom: 5px;
        }
        
        .state-value {
            font-size: 1.5rem;
            font-weight: bold;
            color: #f1c40f;
        }
        
        .transition-display {
            background: rgba(44, 62, 80, 0.7);
            padding: 15px;
            border-radius: 8px;
        }
        
        .transition-display h3 {
            font-size: 0.95rem;
            color: var(--gray);
            display: flex;
            align-items: center;
            gap: 8px;
            margin-bottom: 10px;
        }
        
        .transition-content {
            font-size: 1.1rem;
            font-weight: 600;
            color: var(--success);
            min-height: 40px;
            padding: 10px;
            background: rgba(0, 0, 0, 0.3);
            border-radius: 6px;
            border-left: 4px solid var(--primary);
        }
        
        .explanation {
            background: rgba(44, 62, 80, 0.7);
            padding: 15px;
            border-radius: 8px;
        }
        
        .explanation h3 {
            font-size: 1.2rem;
            color: var(--primary);
            margin-bottom: 15px;
            display: flex;
            align-items: center;
            gap: 10px;
        }
        
        .steps {
            display: flex;
            flex-direction: column;
            gap: 15px;
            margin-top: 15px;
        }
        
        .step {
            background: rgba(25, 35, 60, 0.8);
            padding: 15px;
            border-radius: 8px;
            border-left: 4px solid var(--warning);
            display: flex;
            flex-direction: column;
        }
        
        .step-header {
            display: flex;
            align-items: center;
            gap: 8px;
            margin-bottom: 10px;
            color: #f1c40f;
        }
        
        .step-number {
            width: 25px;
            height: 25px;
            background: rgba(243, 156, 18, 0.2);
            border-radius: 50%;
            display: flex;
            align-items: center;
            justify-content: center;
            font-weight: bold;
            font-size: 0.9rem;
        }
        
        .step-content {
            line-height: 1.5;
            font-size: 0.9rem;
        }
        
        .result-display {
            background: rgba(46, 204, 113, 0.15);
            padding: 15px;
            border-radius: 8px;
            margin-top: 0px;
            border: 2px solid rgba(46, 204, 113, 0.5);
            display: none;
        }
        
        .result-display h3 {
            color: var(--success);
            margin-bottom: 8px;
            display: flex;
            align-items: center;
            gap: 8px;
            font-size: 1.1rem;
        }
        
        .speed-control {
            display: flex;
            align-items: center;
            gap: 12px;
            margin: 0px 0;
            background: rgba(44, 62, 80, 0.7);
            padding: 12px 15px;
            border-radius: 8px;
            justify-content: center;
        }
        
        .speed-control label {
            font-weight: 600;
            display: flex;
            align-items: center;
            gap: 8px;
            font-size: 0.95rem;
        }
        
        #speed {
            flex-grow: 1;
            height: 8px;
            -webkit-appearance: none;
            background: rgba(20, 30, 50, 0.7);
            border-radius: 10px;
            outline: none;
            max-width: 300px;
        }
        
        #speed::-webkit-slider-thumb {
            -webkit-appearance: none;
            width: 20px;
            height: 20px;
            border-radius: 50%;
            background: var(--primary);
            cursor: pointer;
            box-shadow: 0 0 8px rgba(52, 152, 219, 0.7);
        }
        
        #speedValue {
            min-width: 50px;
            text-align: center;
            font-weight: 600;
            color: #f1c40f;
        }
        
        .highlight {
            animation: highlight 1.5s ease;
        }
        
        @keyframes highlight {
            0% { transform: scale(1); box-shadow: 0 0 0 0 rgba(241, 196, 15, 0.5); }
            50% { transform: scale(1.1); box-shadow: 0 0 20px 10px rgba(241, 196, 15, 0.3); }
            100% { transform: scale(1); box-shadow: 0 0 0 0 rgba(241, 196, 15, 0); }
        }

        /* 响应式设计：小屏幕时改为单列布局 */
        @media (max-width: 768px) {
            .main-content {
                flex-direction: column;
            }
            .left-panel, .right-panel {
                width: 100%;
            }
        }
    </style>
</head>
<body>
    <div class="container">
        <header>
            <h1><i class="fas fa-calculator"></i>蛋哥的图灵机模拟器</h1>
            <p class="subtitle">可视化展示图灵机如何执行两个非负整数的加法运算</p>
        </header>
        
        <div class="main-content">
            <!-- 左侧面板 -->
            <div class="left-panel">
                <div class="input-section">
                    <div class="input-group">
                        <label for="num1"><i class="fas fa-hashtag"></i> 第一个数字：</label>
                        <div class="input-wrapper">
                            <input type="number" id="num1" min="0" value="2">
                        </div>
                    </div>
                    
                    <div class="input-group">
                        <label for="num2"><i class="fas fa-hashtag"></i> 第二个数字：</label>
                        <div class="input-wrapper">
                            <input type="number" id="num2" min="0" value="3">
                        </div>
                    </div>
                    
                    <button id="initBtn"><i class="fas fa-play"></i> 初始化</button>
                </div>
                
                <div class="controls">
                    <button id="stepBtn" disabled><i class="fas fa-step-forward"></i> 单步执行</button>
                    <button id="runBtn" disabled><i class="fas fa-play-circle"></i> 开始执行</button>
                    <button id="resetBtn" disabled><i class="fas fa-redo"></i> 重置</button>
                </div>
                
                <div class="speed-control">
                    <label for="speed"><i class="fas fa-tachometer-alt"></i> 执行速度：</label>
                    <input type="range" id="speed" min="1" max="10" value="5">
                    <span id="speedValue">中速</span>
                </div>
                
                <div class="tape-container">
                    <h2 class="panel-title"><i class="fas fa-tape"></i> 图灵机带子</h2>
                    <div class="tape-scroll">
                        <div class="tape" id="tape">
                            <!-- Tape cells will be generated here -->
                        </div>
                    </div>
                </div>
                
                <div class="state-display">
                    <div class="state-icon">
                        <i class="fas fa-microchip"></i>
                    </div>
                    <div class="state-info">
                        <h3>当前状态</h3>
                        <div class="state-value" id="currentState">未初始化</div>
                    </div>
                </div>
                
                <div class="transition-display">
                    <h3><i class="fas fa-exchange-alt"></i> 当前转移函数</h3>
                    <div class="transition-content" id="transition">
                        等待初始化...
                    </div>
                </div>
                
                <div class="result-display" id="resultDisplay">
                    <h3><i class="fas fa-check-circle"></i> 计算结果</h3>
                    <div id="resultContent"></div>
                </div>
            </div>
            
            <!-- 右侧面板 - 添加的说明部分 -->
            <div class="right-panel">
                <div class="explanation">
                    <h3><i class="fas fa-lightbulb"></i> 加法过程说明</h3>
                    <p>此图灵机使用以下状态转移规则执行加法：</p>
                    <div class="steps">
                        <div class="step">
                            <div class="step-header">
                                <div class="step-number">1</div>
                                <h4>状态 q1</h4>
                            </div>
                            <div class="step-content">
                                将第一个数字最左边的1改为0，向右移动，进入状态q2
                            </div>
                        </div>
                        
                        <div class="step">
                            <div class="step-header">
                                <div class="step-number">2</div>
                                <h4>状态 q2</h4>
                            </div>
                            <div class="step-content">
                                向右移动直到找到分隔符0，将其改为1，向左移动，进入状态q3
                            </div>
                        </div>
                        
                        <div class="step">
                            <div class="step-header">
                                <div class="step-number">3</div>
                                <h4>状态 q3</h4>
                            </div>
                            <div class="step-content">
                                向左移动直到找到0，向右移动，进入状态q4
                            </div>
                        </div>
                        
                        <div class="step">
                            <div class="step-header">
                                <div class="step-number">4</div>
                                <h4>状态 q4</h4>
                            </div>
                            <div class="step-content">
                                将找到的第一个1改为0，向右移动，停机（计算结果保留在带子上）
                            </div>
                        </div>
                    </div>
                    
                    <div class="result-info">
                        <p><strong>最终结果</strong>：带子上剩余的1的数量即为计算结果（结果 = n + m）</p>
                    </div>
                </div>
            </div>
        </div>
    </div>

    <script>
        // 图灵机状态定义
        const STATES = {
            Q1: 'q1',
            Q2: 'q2',
            Q3: 'q3',
            Q4: 'q4',
            HALT: '停机'
        };
        
        // 图灵机转移函数
        const TRANSITIONS = {
            // 状态q1：遇到1时写0，右移，进入状态q2
            'q1,1': { write: '0', move: 'R', nextState: STATES.Q2 },
            
            // 状态q2：遇到0时写1，左移，进入状态q3
            'q2,0': { write: '1', move: 'L', nextState: STATES.Q3 },
            // 状态q2：遇到1时保持1，右移，保持状态q2
            'q2,1': { write: '1', move: 'R', nextState: STATES.Q2 },
            
            // 状态q3：遇到0时保持0，右移，进入状态q4
            'q3,0': { write: '0', move: 'R', nextState: STATES.Q4 },
            // 状态q3：遇到1时保持1，左移，保持状态q3
            'q3,1': { write: '1', move: 'L', nextState: STATES.Q3 },
            
            // 状态q4：遇到1时写0，右移，停机
            'q4,1': { write: '1', move: 'R', nextState: STATES.HALT }
        };
        
        // 获取DOM元素
        const tapeEl = document.getElementById('tape');
        const currentStateEl = document.getElementById('currentState');
        const transitionEl = document.getElementById('transition');
        const stepBtn = document.getElementById('stepBtn');
        const runBtn = document.getElementById('runBtn');
        const resetBtn = document.getElementById('resetBtn');
        const initBtn = document.getElementById('initBtn');
        const num1Input = document.getElementById('num1');
        const num2Input = document.getElementById('num2');
        const speedSlider = document.getElementById('speed');
        const speedValueEl = document.getElementById('speedValue');
        const resultDisplay = document.getElementById('resultDisplay');
        const resultContent = document.getElementById('resultContent');
        
        // 图灵机状态变量
        let tape = [];
        let headPosition = 5;
        let currentState = STATES.Q1;
        let intervalId = null;
        let dataStart = 0;
        let dataEnd = 0;
        let initialTape = [];
        
        // 初始化带子
        function initializeTape(num1, num2) {
            // 隐藏结果面板
            resultDisplay.style.display = 'none';
            
            // 创建初始带子（全部为0）
            tape = Array(20).fill('0');
            
            // 根据输入数字计算一元表示
            // 数字n用n+1个1表示
			const unary1 = '1'.repeat(num1);
			const unary2 = '1'.repeat(num2);
            
            // 在带子上写入数字（用0分隔）
            const startPos = 5;
            dataStart = startPos;
            const tapeContent = unary1 + '0' + unary2;
            dataEnd = startPos + tapeContent.length - 1;
            
            // 将内容写入带子
            for (let i = 0; i < tapeContent.length; i++) {
                if (startPos + i < tape.length) {
                    tape[startPos + i] = tapeContent[i];
                } else {
                    tape.push(tapeContent[i]);
                }
            }
            
            // 保存初始带子状态用于重置
            initialTape = [...tape];
            
            // 设置初始读写头位置
            headPosition = startPos;
            
            // 更新UI
            renderTape();
            updateStateDisplay();
            
            // 启用按钮
            stepBtn.disabled = false;
            runBtn.disabled = false;
            resetBtn.disabled = false;
            
            transitionEl.textContent = `初始化完成。输入数据: ${unary1} (数字${num1}) + ${unary2} (数字${num2})`;
        }
        
        // 渲染带子到UI
        function renderTape() {
            tapeEl.innerHTML = '';
            
            // 创建带子头部指示器
            
            
            // 渲染带子单元格
            for (let i = 0; i < tape.length; i++) {
                const cell = document.createElement('div');
                cell.className = 'cell';
                if (i === headPosition) {
                    cell.classList.add('active');
                }
                
                // 标记初始数据区域
                if (i >= dataStart && i <= dataEnd) {
                    cell.style.background = 'rgba(46, 204, 113, 0.15)';
                }
                
                cell.innerHTML = tape[i];
                
                // 添加索引（位置）
                /**const index = document.createElement('div');
                index.className = 'index';
                index.textContent = i;
                cell.appendChild(index);**/
                
                tapeEl.appendChild(cell);
            }
        }
        
        // 执行图灵机的一步操作
        function step() {
            if (currentState === STATES.HALT) {
                clearInterval(intervalId);
                runBtn.innerHTML = '<i class="fas fa-play-circle"></i> 连续执行';
                return;
            }
            
            const currentSymbol = tape[headPosition];
            const transitionKey = `${currentState},${currentSymbol}`;
            const transition = TRANSITIONS[transitionKey];
            
            // 显示当前转移函数
            if (transition) {
                const action = transition.move === 'R' ? '右移' : (transition.move === 'L' ? '左移' : '不动');
                transitionEl.textContent = 
                    `状态: ${currentState}, 读入: ${currentSymbol} → 写入: ${transition.write}, 动作: ${action}, 新状态: ${transition.nextState}`;
            } else {
                transitionEl.textContent = `未定义转移: 状态 ${currentState}, 符号 ${currentSymbol}`;
            }
            
            // 执行转移
            if (transition) {
                // 写入新符号
                tape[headPosition] = transition.write;
                
                // 移动读写头
                if (transition.move === 'R') {
                    headPosition++;
                } else if (transition.move === 'L') {
                    headPosition--;
                }
                
                // 更新状态
                currentState = transition.nextState;
                
                // 确保带子足够长
                if (headPosition >= tape.length) {
                    tape.push('0');
                } else if (headPosition < 0) {
                    tape.unshift('0');
                    headPosition = 0;
                }
            } else {
                // 没有转移函数，停机
                currentState = STATES.HALT;
            }
            
            // 更新UI
            renderTape();
            updateStateDisplay();
            
            if (currentState === STATES.HALT) {
                calculateResult();
            }
        }
        
        // 计算并显示结果
        function calculateResult() {
            // 计算结果：带子上剩余的1的数量
            let oneCount = 0;
            for (let i = 0; i < tape.length; i++) {
                if (tape[i] === '1') oneCount++;
            }
            
            resultDisplay.style.display = 'block';
            const num1 = parseInt(num1Input.value) || 0;
            const num2 = parseInt(num2Input.value) || 0;
            resultContent.innerHTML = `
                <p>${num1} + ${num2} = ${oneCount}</p>
                <p>带子最终状态: ${tape.join('').replace(/0/g, '')}</p>
            `;
            
            // 高亮显示当前单元格
            const activeCell = tapeEl.querySelector('.cell.active');
            if (activeCell) {
                activeCell.classList.add('highlight');
                setTimeout(() => activeCell.classList.remove('highlight'), 1500);
            }
        }
        
        // 更新状态显示
        function updateStateDisplay() {
            currentStateEl.textContent = currentState;
            if (currentState === STATES.HALT) {
                currentStateEl.textContent = "停机";
                stepBtn.disabled = true;
                runBtn.disabled = true;
            }
        }
        
        // 连续执行图灵机
        function run() {
            if (runBtn.innerHTML.includes('play-circle')) {
                runBtn.innerHTML = '<i class="fas fa-pause-circle"></i> 暂停';
                const speed = 1100 - (speedSlider.value * 100);
                intervalId = setInterval(() => {
                    step();
                    if (currentState === STATES.HALT) {
                        clearInterval(intervalId);
                        runBtn.innerHTML = '<i class="fas fa-play-circle"></i> 开始执行';
                    }
                }, speed);
            } else {
                runBtn.innerHTML = '<i class="fas fa-play-circle"></i> 开始执行';
                clearInterval(intervalId);
            }
        }
        
        // 重置图灵机
        function reset() {
            clearInterval(intervalId);
            runBtn.innerHTML = '<i class="fas fa-play-circle"></i> 开始执行';
            
            if (initialTape.length > 0) {
                tape = [...initialTape];
                headPosition = 5;
                currentState = STATES.Q1;
                resultDisplay.style.display = 'none';
                
                renderTape();
                updateStateDisplay();
                transitionEl.textContent = "图灵机已重置";
                
                stepBtn.disabled = false;
                runBtn.disabled = false;
            }
        }
        
        // 更新速度显示
        function updateSpeedDisplay() {
            const speedLabels = ['很慢', '慢', '中速', '快', '很快'];
            const index = Math.floor((speedSlider.value - 1) / 2);
            speedValueEl.textContent = speedLabels[index] || '中速';
        }
        
        // 事件监听器
        initBtn.addEventListener('click', () => {
            const num1 = parseInt(num1Input.value) || 0;
            const num2 = parseInt(num2Input.value) || 0;
            if (num1 < 0 || num2 < 0) {
                alert("请输入非负整数");
                return;
            }
            initializeTape(num1, num2);
        });
        
        stepBtn.addEventListener('click', step);
        runBtn.addEventListener('click', run);
        resetBtn.addEventListener('click', reset);
        speedSlider.addEventListener('input', updateSpeedDisplay);
        
        // 初始化UI
        renderTape();
        updateSpeedDisplay();
        
        // 创建FontAwesome图标的替代方案
        document.head.innerHTML += `
        <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css">
        `;
    </script>
</body>
</html>